﻿using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace IsreversI
{
    struct TurnState
    {
        private enum State
        {
            redturn = 1,
            blueturn = 2,
            gameover = 4,
            invalid = 128 // something suitably large and unlikely to occur at random
        }

        #region member variables
        private State state;
        #endregion

        #region static instances
        public static readonly TurnState RedTurn = new TurnState(State.redturn);
        public static readonly TurnState BlueTurn = new TurnState(State.blueturn);
        public static readonly TurnState GameOver = new TurnState(State.gameover);
        public static readonly TurnState Invalid = new TurnState(State.invalid);
        #endregion

        #region constructors
        private TurnState(State state)
        {
            this.state = state;
        }
        #endregion

        #region public functions
        public TurnState Flipped()
        {
            if (this == RedTurn)
                return BlueTurn;
            else if (this == BlueTurn)
                return RedTurn;
            Debug.Assert(false, "Cannot invert state " + state);
            return Invalid;
        }

        public bool Equals(TurnState s)
        {
            return this.state == s.state;
        }
        #endregion

        #region overides
        public override bool Equals(object obj)
        {
            if (obj == null)
                return false;
            TurnState s = (TurnState)obj;
            return this.state == s.state;
        }

        public override int GetHashCode()
        {
            return (int)this.state;
        }

        public override string ToString()
        {
            switch (this.state)
            {
                case State.redturn:
                    return "Red";
                case State.blueturn:
                    return "Blue";
                case State.gameover:
                    return "GameOver";
                default:
                    return "Invalid";
            }
        }
        #endregion

        #region operator overloads
        static public TurnState operator ~(TurnState state)
        {
            return state.Flipped();
        }

        static public bool operator ==(TurnState f, TurnState s)
        {
            return f.Equals(s);
        }

        static public bool operator !=(TurnState f, TurnState s)
        {
            return !f.Equals(s);
        }

        public static explicit operator PlayerColour(TurnState colour)
        {
            if (colour == RedTurn)
                return PlayerColour.Red;
            else if (colour == BlueTurn)
                return PlayerColour.Blue;
            Debug.Assert(false, "Cannot convert colour " + colour);
            return PlayerColour.Invalid;
        }

        public static explicit operator TileState(TurnState colour)
        {
            return (TileState)(PlayerColour)colour;
        }
        #endregion
    }
}
